package com.frog.lock.starter.core;

import com.frog.lock.starter.annotation.Klock;
import com.frog.lock.starter.model.LockInfo;
import com.frog.lock.starter.model.LockType;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;


public class LockInfoProvider {

    private static final String LOCK_NAME_PREFIX = "lock";
    private static final String LOCK_NAME_SEPARATOR = "_";


    @Autowired
    private BusinessKeyProvider businessKeyProvider;

    private static final Logger logger = LoggerFactory.getLogger(LockInfoProvider.class);

    /**
     * 获取锁的基本信息
     */
    List<LockInfo> get(JoinPoint joinPoint, Klock klock) {
        List<LockInfo> respList = new ArrayList<>();
        // 获取注解中lock type
        LockType type = klock.lockType();
        if (type == null) return respList;
        // 获取注解中lock name
        List<String> businessKeyNames = businessKeyProvider.getKeyName(joinPoint, klock);
        if (businessKeyNames == null || businessKeyNames.isEmpty()) return respList;

        for (String businessKeyName : businessKeyNames) {
            // lockName === lock.klockName.klockKeys
            String lockName = LOCK_NAME_PREFIX + LOCK_NAME_SEPARATOR + getAnnotationName(klock.name()) + LOCK_NAME_SEPARATOR + getBusinessName(businessKeyName);
            long waitTime = getWaitTime(klock);
            long leaseTime = getLeaseTime(klock);
            //如果占用锁的时间设计不合理，则打印相应的警告提示
            if (leaseTime == -1 && logger.isWarnEnabled()) {
                logger.warn("Trying to acquire Lock({}) with no expiration,Klock will keep prolong the lock expiration while the lock is still holding by current thread.This may cause dead lock in some circumstances.", lockName);
            }
            // 将锁对象添加集合
            LockInfo lockInfo = new LockInfo(type, lockName, waitTime, leaseTime);
            respList.add(lockInfo);
        }
        return respList;
    }


    /**
     * 获取锁的name，如果没有指定，取UUID
     */
    private String getBusinessName(String businessKeyName) {
        return "".equals(businessKeyName) || businessKeyName == null ? "" : businessKeyName.replace(":", "-");
    }

    /**
     * 获取锁的name
     */
    private String getAnnotationName(String annotationName) {
        return "".equals(annotationName) || annotationName == null ? "" : annotationName.replace(":", "-");
    }


    private final static long waitTime = 2;
    private final static long leaseTime = 2;


    /**
     * 锁等待时间
     */
    private long getWaitTime(Klock lock) {
        return lock.waitTime() == Long.MIN_VALUE ? waitTime : lock.waitTime();
    }


    /**
     * 锁超时时间
     */
    private long getLeaseTime(Klock lock) {
        return lock.leaseTime() == Long.MIN_VALUE ? leaseTime : lock.leaseTime();
    }
}
